import { _decorator, Component, Node,Prefab,SpriteFrame,UITransform,instantiate,SystemEvent,EventTouch,Vec3,v3,Size,View,v2,Vec2,EditBox } from 'cc';
import {EditorBall} from "./EditorBall";
import {BallColorIdx} from "../GameConfig";
import LineGameLevelData from "./LineGameLevelData";
import LineGameBallData from "./LineGameBallData";
const { ccclass, property } = _decorator;

@ccclass('LineGameEditor')
export class LineGameEditor extends Component {

    @property({type:Prefab})
    ballPrefab:Prefab=null;

    @property({type:[SpriteFrame]})
    ballSpriteFrames:Array<SpriteFrame>=[];

    public touchTransInput:Vec3=v3(0,0,0);
    public touchTransOutput:Vec3=v3(0,0,0);

    //屏幕尺寸
    public canvasSize:Size=null;
    public visibleSize:Size=null;
    public designXRatio:number=1;
    public designYRatio:number=1;

    public gameBoardNode:Node=null;
    public gameBoradUITrans:UITransform=null;
    public ballsParentNode:Node=null;
    public selNode:Node=null;

    public levelIdEditBox:EditBox=null;
    public stepsNumEditBox:EditBox=null;

    public dataEditBox:EditBox=null;

    public balls:Array<EditorBall>=[];
    public curSelBall:EditorBall=null;

    //关卡数据对象
    public levelData:LineGameLevelData=new LineGameLevelData();

    public inited:boolean=false;

    public static instance=null;

    onLoad()
    {
        LineGameEditor.instance=this;

        this.canvasSize=View.instance.getCanvasSize();
        console.log("** canvasSize="+JSON.stringify(this.canvasSize));

        this.visibleSize=View.instance.getVisibleSize();
        console.log("** visibleSize="+JSON.stringify(this.visibleSize));

        this.designXRatio=this.visibleSize.width / this.canvasSize.width;
        this.designYRatio=this.visibleSize.height / this.canvasSize.height;

        this.init();
    }

    start()
    {
        this.addEvent();
    }

    addEvent()
    {
        //systemEvent.on(SystemEvent.EventType.TOUCH_START, this.onTouchStart, this);

        this.gameBoardNode.on(SystemEvent.EventType.TOUCH_START, this.onTouchStart, this);
        this.gameBoardNode.on(SystemEvent.EventType.TOUCH_MOVE, this.onTouchMove, this);
        this.gameBoardNode.on(SystemEvent.EventType.TOUCH_END, this.onTouchEnd, this);
        this.gameBoardNode.on(SystemEvent.EventType.TOUCH_CANCEL, this.onTouchCancel, this);
    }

    public updateTouchTransOutput(touchX:number, touchY:number)
    {
        this.touchTransInput.x=touchX;
        this.touchTransInput.y=touchY;
        this.touchTransInput.z=0;
        this.gameBoradUITrans.convertToNodeSpaceAR(this.touchTransInput, this.touchTransOutput);
    }

    onTouchStart(event:EventTouch)
    {
        let touchX=event.getLocationX() * this.designXRatio;
        let touchY=event.getLocationY() * this.designYRatio;

        //转换到ballParent坐标系下
        this.updateTouchTransOutput(touchX, touchY);

        let touchBall:EditorBall=null;
        for(let i=0;i<this.balls.length;i++)
        {
            if(this.balls[i].isInRect(v2(this.touchTransOutput.x, this.touchTransOutput.y)))
            {
                this.selBall(this.balls[i]);
                return;
            }
        }

        if(touchBall===null)
        {
            this.cancelSelBall();
        }
    }


    public selBall(ball:EditorBall)
    {
        if(!ball)
            return;
        this.curSelBall=ball;
        this.selNode.active=true;
        this.selNode.setPosition(this.curSelBall.node.getPosition());
    }

    public cancelSelBall()
    {
        this.curSelBall=null;
        this.selNode.active=false;
    }

    onTouchMove(event:EventTouch)
    {
        if(!this.curSelBall)
            return;
        let touchX=event.getLocationX() * this.designXRatio;
        let touchY=event.getLocationY() * this.designYRatio;
        this.updateTouchTransOutput(touchX, touchY);

        this.curSelBall.node.setPosition(this.touchTransOutput.x, this.touchTransOutput.y, 0);
    }

    //Touch结束的逻辑
    onTouchEnd(event:EventTouch)
    {
        let touchX=event.getLocationX();
        let touchY=event.getLocationY();

        this.touchEnd();
    }

    onTouchCancel(event:EventTouch)
    {
        this.touchEnd();
    }

    public touchEnd()
    {

    }

    public init()
    {
        if(this.inited)
            return;

        this.gameBoardNode=this.node.getChildByName("gameBoard");
        this.gameBoradUITrans=this.gameBoardNode.getComponent(UITransform);
        this.ballsParentNode=this.gameBoardNode.getChildByName("ballsParent");
        this.selNode=this.gameBoardNode.getChildByName("sel");

        let UINode:Node=this.node.parent.getChildByName("UI");
        this.levelIdEditBox=UINode.getChildByName("levelIdEditBox").getComponent(EditBox);
        this.stepsNumEditBox=UINode.getChildByName("stepsNumEditBox").getComponent(EditBox);
        this.dataEditBox=UINode.getChildByName("dataEditBox").getComponent(EditBox);

        this.inited=true;
    }

    public getBallSpriteFrame(idx:number):SpriteFrame
    {
        if(idx>=0 && idx<this.ballSpriteFrames.length)
            return this.ballSpriteFrames[idx];
        return null;
    }

    public addBallClicked(target , arg)
    {
        let parent:Node=new Node();
        this.ballsParentNode.addChild(parent);

        let childrenCount:number=this.ballsParentNode.children.length;

        let ballObj=instantiate(this.ballPrefab);
        parent.addChild(ballObj);
        let ballComponent:EditorBall=ballObj.getComponent("EditorBall");
        ballComponent.setVal(arg);
        ballComponent.setIdx(childrenCount-1, 0);
        this.balls.push(ballComponent);

        let ballObj2=instantiate(this.ballPrefab);
        parent.addChild(ballObj2);
        let ballComponent2:EditorBall=ballObj2.getComponent("EditorBall");
        ballComponent2.setVal(arg);
        ballComponent2.setIdx(childrenCount-1, 1);
        ballObj2.setPosition(150, -150, 0);
        this.balls.push(ballComponent2);
    }

    public delBallClicked()
    {
        if(!this.curSelBall)
            return;

        //先从balls数组中移除
        this.removeBallPair(this.curSelBall.idx);

        this.curSelBall.node.parent.removeFromParent(true);
        this.curSelBall.node.parent.destroy();

        this.cancelSelBall();

        //更新balls的id
        this.updateBallsIdx();
    }

    public updateBallsIdx()
    {
        //console.log("** parent children len="+this.ballsParentNode.children.length);
        for(let i=0;i<this.ballsParentNode.children.length;i++)
        {
            for(let j=0;j<this.ballsParentNode.children[i].children.length;j++)
            {
                let ballComponent:EditorBall=this.ballsParentNode.children[i].children[j].getComponent("EditorBall");

                //console.log("** updateIdx i="+i);
                ballComponent.updateIdx(i);
            }
        }
    }

    public removeBallPair(id:number)
    {
        let cnt:number=this.balls.length;
        for(let i=0;i<this.balls.length;)
        {
            if(this.balls[i].idx===id)
            {
                console.log("** del ball="+this.balls[i].idx+"-"+this.balls[i].subIdx);
                this.balls.splice(i, 1);
            }
            else
            {
                i++;
            }
            //console.log("** loop i="+i);
        }

        console.log("** balls len="+this.balls.length);
    }

    public exportClicked()
    {
        //console.log("** levelId="+this.levelIdEditBox.string+"   steps="+this.stepsNumEditBox.string);

        this.levelData.reset();
        this.levelData.id=parseInt(this.levelIdEditBox.string);
        this.levelData.type=1;
        this.levelData.diff=1;
        this.levelData.step=parseInt(this.stepsNumEditBox.string);

        let ballPos:Vec3=null;

        for(let i=0;i<this.ballsParentNode.children.length;i++)
        {
            let ballData:LineGameBallData=new LineGameBallData();
            let ballComponent0:EditorBall=this.ballsParentNode.children[i].children[0].getComponent("EditorBall");

            ballData.val=ballComponent0.val;
            ballPos=ballComponent0.node.getPosition();
            ballData.pos0.set(Math.floor(ballPos.x), Math.floor(ballPos.y));

            let ballComponent1:EditorBall=this.ballsParentNode.children[i].children[1].getComponent("EditorBall");
            ballPos=ballComponent1.node.getPosition();
            ballData.pos1.set(Math.floor(ballPos.x), Math.floor(ballPos.y));

            this.levelData.balls.push(ballData);
        }

        let dataStr:string=JSON.stringify(this.levelData);
        this.dataEditBox.string=dataStr;
        //console.log("** levelData="+dataStr);
    }

    public importClicked()
    {
        if(this.dataEditBox.string.length<1)
            return;
        let dataObj=JSON.parse(this.dataEditBox.string);
        this.levelIdEditBox.string=""+dataObj.id;
        this.stepsNumEditBox.string=""+dataObj.step;

        //清除所有球
        this.clearAllBalls();

        for(let i=0;i<dataObj.balls.length;i++)
        {
            let val:number=parseInt(dataObj.balls[i].val);

            let parent:Node=new Node();
            this.ballsParentNode.addChild(parent);

            let childrenCount:number=this.ballsParentNode.children.length;

            let ballObj=instantiate(this.ballPrefab);
            parent.addChild(ballObj);
            let ballComponent:EditorBall=ballObj.getComponent("EditorBall");
            ballComponent.setVal(val);
            ballComponent.setIdx(childrenCount-1, 0);
            ballObj.setPosition(dataObj.balls[i].pos0.x, dataObj.balls[i].pos0.y,0);
            this.balls.push(ballComponent);

            let ballObj2=instantiate(this.ballPrefab);
            parent.addChild(ballObj2);
            let ballComponent2:EditorBall=ballObj2.getComponent("EditorBall");
            ballComponent2.setVal(val);
            ballComponent2.setIdx(childrenCount-1, 1);
            ballObj2.setPosition(dataObj.balls[i].pos1.x, dataObj.balls[i].pos1.y,0);
            this.balls.push(ballComponent2);
        }
    }

    public clearAllBalls()
    {
        this.cancelSelBall();

        this.balls.splice(0, this.balls.length);

        this.ballsParentNode.destroyAllChildren();
        this.ballsParentNode.removeAllChildren(true);
    }

    update(deltaTime: number) {

        if(this.curSelBall)
        {
            this.selNode.setPosition(this.curSelBall.node.getPosition());
        }
    }
}

